package com.pascualabs.android.lwplantilla;

import java.util.Random;

import org.andengine.engine.LimitedFPSEngine;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;

import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.particle.BatchedSpriteParticleSystem;
import org.andengine.entity.particle.ParticleSystem;
import org.andengine.entity.particle.emitter.PointParticleEmitter;
import org.andengine.entity.particle.initializer.AccelerationParticleInitializer;
import org.andengine.entity.particle.initializer.BlendFunctionParticleInitializer;
import org.andengine.entity.particle.initializer.RotationParticleInitializer;
import org.andengine.entity.particle.initializer.VelocityParticleInitializer;
import org.andengine.entity.particle.initializer.GravityParticleInitializer;
import org.andengine.entity.particle.modifier.AlphaParticleModifier;
import org.andengine.entity.particle.modifier.ExpireParticleInitializer;
import org.andengine.entity.particle.modifier.RotationParticleModifier;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.sprite.UncoloredSprite;
import org.andengine.extension.ui.livewallpaper.BaseLiveWallpaperService;
import org.andengine.input.sensor.acceleration.AccelerationData;
import org.andengine.input.sensor.acceleration.IAccelerationListener;

import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.atlas.bitmap.BuildableBitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.source.IBitmapTextureAtlasSource;
import org.andengine.opengl.texture.atlas.buildable.builder.BlackPawnTextureAtlasBuilder;
import org.andengine.opengl.texture.atlas.buildable.builder.ITextureAtlasBuilder.TextureAtlasBuilderException;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.util.debug.Debug;

import android.content.res.Configuration;
import android.opengl.GLES20;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;

public class LiveWallpaperService extends BaseLiveWallpaperService implements
		IAccelerationListener {

	// ================================================================================
	// Fields
	// ================================================================================
	private static final int MAX_FRAMES_PER_SECOND = 16;

	private static int CAMERA_WIDTH = 480;
	private static int CAMERA_HEIGHT = 800;

	private Camera mCamera;
	private Scene mScene;

	private ITextureRegion mFlowerTextureRegion;
	private BitmapTextureAtlas mFlowerTexture;
	private VelocityParticleInitializer<UncoloredSprite> mVelocityParticleInitializer;

	private String mBackground;

	private BuildableBitmapTextureAtlas mEcchiTextureAtlas;
	private BuildableBitmapTextureAtlas mEcchiTextureAtlash;
	private TiledTextureRegion mSpringecchi;
	private TiledTextureRegion mSpringecchih;

	private AnimatedSprite ecchi;

	private boolean vertical = true;

	Random rnd = new Random();
	Display display;
	RatioResolutionPolicy ratio;

	private int rotation;
	private float centerX;
	private float centerY;

	private BitmapTextureAtlas taFondo;

	private TextureRegion mFondoNavidadTextureRegion;

	private SpriteBackground bg1;

	private Object mFondoNavidadTextureRegion2;

	private BitmapTextureAtlas taFondo2;

	@Override
	public EngineOptions onCreateEngineOptions() {

		final DisplayMetrics displayMetrics = new DisplayMetrics();
		WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
		wm.getDefaultDisplay().getMetrics(displayMetrics);
		wm.getDefaultDisplay().getRotation();
		int width = displayMetrics.widthPixels;
		int height = displayMetrics.heightPixels;

		display = ((WindowManager) getSystemService(WINDOW_SERVICE))
				.getDefaultDisplay();

		CAMERA_WIDTH = 480;
		CAMERA_HEIGHT = 800;
		LiveWallpaperPreferences.getInstance().initPreferences(this);
		mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		EngineOptions options = new EngineOptions(true,
				ScreenOrientation.PORTRAIT_FIXED, new RatioResolutionPolicy(
						CAMERA_WIDTH, CAMERA_HEIGHT), mCamera);

		if (width > height) {
			vertical = false;
		} else {
			vertical = true;
		}

		return options;
	}

	@Override
	public void onCreateResources(
			OnCreateResourcesCallback createResourcesCallback) throws Exception {
		this.mFlowerTexture = new BitmapTextureAtlas(this.getTextureManager(),
				64, 64, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mFlowerTextureRegion = BitmapTextureAtlasTextureRegionFactory
				.createFromAsset(this.mFlowerTexture, this,
						"gfx/rosetrans64.png", 0, 0);
		this.getEngine().getTextureManager().loadTexture(this.mFlowerTexture);
		this.enableAccelerationSensor(this);

		// PRIMAVERA
		this.mEcchiTextureAtlas = new BuildableBitmapTextureAtlas(
				this.getTextureManager(), 2048, 3072, TextureOptions.NEAREST);
		this.mSpringecchi = BitmapTextureAtlasTextureRegionFactory
				.createTiledFromAsset(this.mEcchiTextureAtlas, this,
						"gfx/tilecchi.png", 3, 3);

		this.mEcchiTextureAtlash = new BuildableBitmapTextureAtlas(
				this.getTextureManager(), 3072, 2048, TextureOptions.NEAREST);
		this.mSpringecchih = BitmapTextureAtlasTextureRegionFactory
				.createTiledFromAsset(this.mEcchiTextureAtlash, this,
						"gfx/tilecchih.png", 3, 3);

		try {
			this.mEcchiTextureAtlas
					.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(
							0, 0, 1));
			this.mEcchiTextureAtlas.load();

			this.mEcchiTextureAtlash
					.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(
							0, 0, 1));
			this.mEcchiTextureAtlash.load();
		} catch (TextureAtlasBuilderException e) {
			Debug.e(e);
		}

		this.taFondo = new BitmapTextureAtlas(getTextureManager(), 2048, 2048);
		this.taFondo2 = new BitmapTextureAtlas(getTextureManager(), 2048, 2048);
		this.mFondoNavidadTextureRegion = BitmapTextureAtlasTextureRegionFactory
				.createFromAsset(taFondo, this, "gfx/forest_480x800.png", 0, 0);
		this.mFondoNavidadTextureRegion2 = BitmapTextureAtlasTextureRegionFactory
				.createFromAsset(taFondo2, this, "gfx/forest_800x480.png", 0, 0);
		this.taFondo.load();
		this.taFondo2.load();

		createResourcesCallback.onCreateResourcesFinished();
	}

	@Override
	public org.andengine.engine.Engine onCreateEngine(
			final EngineOptions pEngineOptions) {
		return new LimitedFPSEngine(pEngineOptions, MAX_FRAMES_PER_SECOND);

	}

	@Override
	public void onCreateScene(OnCreateSceneCallback createSceneCallback)
			throws Exception {
		mScene = new Scene();
		mScene.setRotationCenter(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2);

		// FONDO
		mBackground = LiveWallpaperPreferences.getInstance().getBackground();
		if (mBackground.equals("Black")) {
			mScene.setBackground(new Background(0.0f, 0.0f, 0.0f));
		} else if (mBackground.equals("Green")) {
			mScene.setBackground(new Background(0.0f, 0.9f, 0.0f));
		} else if (mBackground.equals("Blue")) {
			bg1 = new SpriteBackground(new Sprite(centerX, centerY,
					this.mFondoNavidadTextureRegion,
					this.getVertexBufferObjectManager()));
			this.mScene.setBackground(bg1);
		}

		//
		// PRIMAVERA
		// updateBackground();
		// resetBody();

		// if(vertical){
		// ecchi = new AnimatedSprite(0, 0,
		// this.mSpringecchi,this.getVertexBufferObjectManager());
		// ecchi.setCurrentTileIndex(5);
		// mScene.attachChild(ecchi);
		// }else{
		// ecchi = new AnimatedSprite(0, 0,
		// this.mSpringecchih,this.getVertexBufferObjectManager());
		// ecchi.setCurrentTileIndex(5);
		// mScene.attachChild(ecchi);
		// }

		ecchi = new AnimatedSprite(0, 0, this.mSpringecchi,
				this.getVertexBufferObjectManager());
		ecchi.setCurrentTileIndex(5);
		mScene.attachChild(ecchi);

		// PARTICLES

		// set the x y values of where the petals fall from
		final int mParticleX = CAMERA_WIDTH / 2;
		final int mParticleY = 0;
		// Set the max and min rates that particles are generated per second
		final int mParticleMinRate = 1;
		final int mParticleMaxRate = 2;
		// Set a variable for the max particles in the system.
		final int mParticleMax = 40;
		final ParticleSystem particleSystem = createParticleSystem(null);
		// attach particle system to scene
		this.mScene.attachChild(particleSystem);

		createSceneCallback.onCreateSceneFinished(mScene);
	}

	private void resetBody() {

	}

	@Override
	public void onPopulateScene(Scene arg0,
			OnPopulateSceneCallback populateSceneCallback) throws Exception {
		populateSceneCallback.onPopulateSceneFinished();
	}

	// enable sensors when resumed
	@Override
	public void onResumeGame() {
		mBackground = LiveWallpaperPreferences.getInstance().getBackground();
		if (mBackground.equals("Black")) {
			mScene.setBackground(new Background(0.0f, 0.0f, 0.0f));
		} else if (mBackground.equals("Green")) {
			mScene.setBackground(new Background(0.0f, 0.9f, 0.0f));
		} else if (mBackground.equals("Blue")) {
			// mScene.setBackground(new Background(0.0f, 0.0f, 0.9f));
			bg1 = new SpriteBackground(new Sprite(centerX, centerY,
					this.mFondoNavidadTextureRegion,
					this.getVertexBufferObjectManager()));
			this.mScene.setBackground(bg1);
		}

		super.onResumeGame();
		this.enableAccelerationSensor(this);
	}

	// Disable sensors when game is paused to save battery life
	protected boolean disableAccelerationSensor() {
		return this.mEngine.disableAccelerationSensor(this);
	}

	@Override
	public void onPauseGame() {
		super.onPauseGame();
		this.disableAccelerationSensor();
	}

	@Override
	public void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {
		// TODO Auto-generated method stub

	}

	// Change the petals to move along the axes of the accelerometer
	@Override
	public void onAccelerationChanged(AccelerationData pAccelerationData) {
		final float minVelocityX = (pAccelerationData.getX() + 2) * 2;
		final float maxVelocityX = (pAccelerationData.getX() - 2) * 2;
		final float minVelocityY = (pAccelerationData.getY() - 4) * 5;
		final float maxVelocityY = (pAccelerationData.getY() - 6) * 5;
		this.mVelocityParticleInitializer.setVelocity(minVelocityX,
				maxVelocityX, minVelocityY, maxVelocityY);
		try {
			updateBody(pAccelerationData.getX());
		} catch (Error e) {
			e.getMessage();
		}

	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		// if (vertical == true) {
		// if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
		// mScene.setScale(1);
		// mScene.setPosition(0, 0);
		// } else if (newConfig.orientation ==
		// Configuration.ORIENTATION_LANDSCAPE) {
		// mScene.setScaleY(1.6f);
		// mScene.setScaleX(0.6f);
		// mScene.setPosition(120, -240);
		// }
		// } else if (vertical == false) {
		// if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
		// mScene.setScaleY(0.6f);
		// mScene.setScaleX(1.6f);
		// mScene.setPosition(-240, 120);
		// } else if (newConfig.orientation ==
		// Configuration.ORIENTATION_LANDSCAPE) {
		// mScene.setScale(1);
		// mScene.setPosition(0, 0);
		// }
		// }
		// if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
		// //mScene.setScale(1);
		// //mScene.setPosition(0, 0);
		// vertical = true;
		// } else if (newConfig.orientation ==
		// Configuration.ORIENTATION_LANDSCAPE) {
		// //mScene.setScaleY(1.6f);
		// //mScene.setScaleX(0.6f);
		// //ecchi.registerEntityModifier(new ScaleModifier(1,1,0.6f,1,0.6f));
		// //ecchi.setPosition(120, -240);
		// vertical = false;
		// }
		updateBackground();
	}

	private void updateBody(float x) {
		if (x < 0) {
			if (ecchi.getCurrentTileIndex() - 1 >= 0) {
				ecchi.reset();
				ecchi.setCurrentTileIndex(ecchi.getCurrentTileIndex() - 1);
			}
		} else if (x > 0) {

			if (ecchi.getCurrentTileIndex() + 1 <= 8) {
				ecchi.reset();
				ecchi.setCurrentTileIndex(ecchi.getCurrentTileIndex() + 1);
			}
		}
	}

	public ParticleSystem createParticleSystem(
			final TextureRegion mFlowerTextureRegion) {

		final float maxRate = 10;
		final float minRate = 5;

		// set the x y values of where the petals fall from
		final int mParticleX = CAMERA_WIDTH / 2;
		final int mParticleY = 0;
		// Set the max and min rates that particles are generated per second
		final int mParticleMinRate = 1;
		final int mParticleMaxRate = 2;
		// Set a variable for the max particles in the system.
		final int mParticleMax = 40;

		final PointParticleEmitter pointParticleEmitter = new PointParticleEmitter(
				mParticleX, mParticleY);

		final BatchedSpriteParticleSystem particleSystem = new BatchedSpriteParticleSystem(
				pointParticleEmitter, mParticleMinRate, mParticleMaxRate,
				mParticleMax, this.mFlowerTextureRegion,
				this.getVertexBufferObjectManager());

		particleSystem
				.addParticleInitializer(new BlendFunctionParticleInitializer<UncoloredSprite>(
						GLES20.GL_SRC_ALPHA, GLES20.GL_ONE));
		// set initial velocity
		this.mVelocityParticleInitializer = new VelocityParticleInitializer<UncoloredSprite>(
				-100, 100, 20, 190);
		particleSystem
				.addParticleInitializer(this.mVelocityParticleInitializer);

		// add gravity so the particles fall downward
		particleSystem
				.addParticleInitializer(new GravityParticleInitializer<UncoloredSprite>());
		// add acceleration so particles float
		particleSystem
				.addParticleInitializer(new AccelerationParticleInitializer<UncoloredSprite>(
						0, -10));
		// add a rotation to particles
		particleSystem
				.addParticleInitializer(new RotationParticleInitializer<UncoloredSprite>(
						0.0f, 90.0f));
		// have particles expire after 40
		particleSystem
				.addParticleInitializer(new ExpireParticleInitializer<UncoloredSprite>(
						40.0f));

		// change rotation of particles at various times
		particleSystem
				.addParticleModifier(new RotationParticleModifier<UncoloredSprite>(
						0.0f, 10.0f, 0.0f, -180.0f));
		particleSystem
				.addParticleModifier(new RotationParticleModifier<UncoloredSprite>(
						10.0f, 20.0f, -180.0f, 90.0f));
		particleSystem
				.addParticleModifier(new RotationParticleModifier<UncoloredSprite>(
						20.0f, 30.0f, 90.0f, 0.0f));
		particleSystem
				.addParticleModifier(new RotationParticleModifier<UncoloredSprite>(
						30.0f, 40.0f, 0.0f, -90.0f));
		// add some fade in and fade out to the particles
		particleSystem
				.addParticleModifier(new AlphaParticleModifier<UncoloredSprite>(
						0.0f, 10.f, 0.8f, 1.0f));
		particleSystem
				.addParticleModifier(new AlphaParticleModifier<UncoloredSprite>(
						25.0f, 40.0f, 1.0f, 0.0f));
		return particleSystem;
	}

	public void updateBackground() {
		rotation = display.getRotation();
		display = ((WindowManager) getSystemService(WINDOW_SERVICE))
				.getDefaultDisplay();
		
		

		if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {

			// centerX = (CAMERA_HEIGHT -
			// mFondoNavidadTextureRegion2.getWidth()) / 2;
			// centerY = (CAMERA_WIDTH -
			// mFondoNavidadTextureRegion2.getHeight()) / 2;
			// bg2 = new SpriteBackground(new Sprite(centerX, centerY,
			// this.mFondoNavidadTextureRegion2,
			// this.getVertexBufferObjectManager()));
			// this.scene.setBackground(bg2);
			ecchi = new AnimatedSprite(0, 0, this.mSpringecchi,
					this.getVertexBufferObjectManager());
			ecchi.setCurrentTileIndex(5);
			mScene.attachChild(ecchi);
			mCamera.set(0, 0, CAMERA_HEIGHT, CAMERA_WIDTH);
			vertical = false;

		} else if (rotation == Surface.ROTATION_0
				|| rotation == Surface.ROTATION_180) {

			// centerX = (CAMERA_WIDTH - mFondoNavidadTextureRegion.getWidth())
			// / 2;
			// centerY = (CAMERA_HEIGHT -
			// mFondoNavidadTextureRegion.getHeight()) / 2;
			// bg1 = new SpriteBackground(new Sprite(centerX, centerY,
			// this.mFondoNavidadTextureRegion,
			// this.getVertexBufferObjectManager()));
			// this.scene.setBackground(bg1);
			ecchi = new AnimatedSprite(0, 0, this.mSpringecchi,
					this.getVertexBufferObjectManager());
			ecchi.setCurrentTileIndex(5);
			mScene.attachChild(ecchi);
			mCamera.set(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
			vertical = true;

		}
	}
}
